/* 
 * File:   MotionDetector.cpp
 * Author: root
 * 
 * Created on October 29, 2015, 12:55 AM
 */

#include "MotionDetector.h"
#include "RawData.h"
#include "Buffer.h"
#include <cmath>
#include <iostream>

using namespace std;

MotionDetector* MotionDetector::instance = 0;

MotionDetector::MotionDetector() {

    this->runTime = 0;
    this->motion = 4116;
    this->time = 0;
}

MotionDetector::MotionDetector(const MotionDetector& orig) {
	this->motion = orig.motion;
	this->runTime = orig.runTime;
	this->time = orig.time;
}

MotionDetector::~MotionDetector() {
}

MotionDetector* MotionDetector::getInstance()
{
  if ( !MotionDetector::instance )
  {
        MotionDetector::instance = new MotionDetector();
  }
  return MotionDetector::instance;
}

uint32 MotionDetector::get()
{
    return this->motion;
}

bool MotionDetector::checkVariance(const RawData *paraRawA, const RawData *paraRawB)
{
    bool result = true; 
  
    if (fabs(paraRawA->xAxis - paraRawB->xAxis) <= 0.4) {
        if(fabs(paraRawA->yAxis - paraRawB->yAxis) <= 0.4) {
            if(fabs(paraRawA->zAxis - paraRawB->zAxis) <= 0.4) {
                result = false;
            }
        }
    }
    return result;
}


//uint32 MotionDetector::update(const RawData *paraRaw)
//{
//    uint32 tempData = 0;
//    
//    if (this->motion != 50 && this->motion != 20)
//    {
//        this->motion = 4116;
////        this->cnt = 0;
//
//        if(this->rawBuffer.cnt > 0) {
//            if((paraRaw->time <= this->rawBuffer.back()->time) 
//                    || (paraRaw->time > (this->rawBuffer.back()->time + 100)))
//            {
//                this->rawBuffer.bottom = 0;
//                this->rawBuffer.top = 0;
//                this->rawBuffer.cnt = 0;
//            }
//        }
//    
//        if (this->rawBuffer.cnt > 3) 
//        {
//            this->rawBuffer.bottom = (this->rawBuffer.bottom + 1) % 4;
//            this->rawBuffer.cnt--;
//        }
//        
//        this->rawBuffer.data[this->rawBuffer.top] = *paraRaw;
//        this->rawBuffer.cnt++;
//        this->rawBuffer.top = (this->rawBuffer.top + 1) % 4;
//    
//        tempData = 1;
//        if ( this->rawBuffer.cnt > 1 )
//        {
//            while ( tempData < this->rawBuffer.cnt )
//            {
//
//                if(this->checkVariance(&this->rawBuffer.data[0], &this->rawBuffer.data[tempData++]))
//
//                {
//                    this->motion = 20;
//                    this->time = paraRaw->time;
//                    return this->motion;
//                }
//            }
//            if ( this->rawBuffer.cnt > 3 )
//                this->motion = 0;
//        }
//    }
//    return this->motion;
//}

uint32 MotionDetector::update(const RawData *paraRaw)
{
    uint32 tempData = 0;
	uint32 tempMotion = this->motion;
    
    if (tempMotion != 50 && tempMotion != 20)
    {
        this->motion = 4116;
//        this->cnt = 0;

        if(this->rawBuffer.cnt > 0) {
            if((paraRaw->time <= this->rawBuffer.back()->time) 
                    || (paraRaw->time > (this->rawBuffer.back()->time + 100)))
            {
                this->rawBuffer.bottom = 0;
                this->rawBuffer.top = 0;
                this->rawBuffer.cnt = 0;
            }
        }
    
        if (this->rawBuffer.cnt > 3) 
        {
            this->rawBuffer.bottom = (this->rawBuffer.bottom + 1) % 4;
            this->rawBuffer.cnt--;
        }
        
        this->rawBuffer.data[this->rawBuffer.top] = *paraRaw;
        this->rawBuffer.cnt++;
        this->rawBuffer.top = (this->rawBuffer.top + 1) % 4;
    
        tempData = 1;
        if ( this->rawBuffer.cnt > 1 )
        {
            while ( tempData < this->rawBuffer.cnt )
            {

                if(this->checkVariance(&this->rawBuffer.data[0], &this->rawBuffer.data[tempData]))

                {
                	tempMotion = 20;
                    this->motion = 20;
                    this->time = paraRaw->time;
                    return tempMotion;
                }
				++tempData;
            }
            if ( this->rawBuffer.cnt > 3 )
                this->motion = 0;
        }
		tempMotion = this->motion;
    }
    return tempMotion;
}

//uint32 MotionDetector::update(uint32 time, double diff)
//{
//    uint32 tempData = 0;
//    uint32 motion = this->motion;
//    
//    if (motion && motion != 4116)
//    {
//        if(diff < 16) 
//        {
//            if(time > this->time + 20000) 
//            {
//LABEL_14:
//                this->motion = tempData;
//                goto LABEL_15;
//            }
//        } else {
//            this->time = time;
//            if(diff > 3600) {
//                this->runTime = time;
//                tempData = 50;
//                goto LABEL_15;
//            }
//            if (diff <= 2500) {
//                if (motion != 50 || time <= (this->runTime + 5000))
//                    goto LABEL_15;
//                tempData = 20;
//                goto LABEL_15;
//            }
//            this->runTime = time;
//        }
//LABEL_15:
//        this->motion = tempData;
//    }
//    return this->motion;
//}

uint32 MotionDetector::update(uint32 time, double diff)
{
    uint32 tempData = 0;
    uint32 motion = this->motion;
    
    if (motion && motion != 4116)
    {
        if(diff < 16) 
        {
            if(time > (this->time + 20000))
            {
LABEL_14:
                this->motion = tempData;
                goto LABEL_15;
            }
        } else {
            this->time = time;
            if(diff > 3600) {
                this->runTime = time;
                tempData = 50;
				if(motion == 50)
					goto LABEL_15;
                goto LABEL_14;
            }
            if (diff <= 2500) {
                if (motion != 50 || time <= (this->runTime + 5000))
                    goto LABEL_15;
                tempData = 20;
                goto LABEL_15;
            }
            this->runTime = time;
        }
LABEL_15:
        motion = this->motion;
    }
    return motion;
}

void MotionDetector::release()
{
    if ( this->getInstance() )
    {
        delete this->getInstance();
        cout<<"MotionDetector::release\n";
    }
}


